import xml.etree.ElementTree as ET
import osm_utils as osm
import math
import random
import pickle

DEFAULT_FILE = 'israel_and_palestine.osm'

RAW_NODE_TABLE = {}

# Changed for version 2!
#ALL_LINKS = False
ALL_LINKS = True

MAP = osm.CountryMap()

def GetJunctionType(node):
    tags = node.findall('tag')
    for tag in tags:
        if tag.get('k') == 'highway':
            return tag.get('v')
    return None
    
def GetHighwayType(way):
    tags = way.findall('tag')
    for tag in tags:
        if tag.get('k') == 'highway':
            return tag.get('v')
    return None

def GetHighwayTypeIndex(highway_type):
    return osm.DRIVEABLE_HIGHWAYS.index(highway_type)


def OnewayStreet(way):
    tags = way.findall('tag')
    for tag in tags:
        if tag.get('k') == 'oneway' and tag.get('v') == 'yes':
            return True
    return False
    
def JunctionName(node):
    tags = node.findall('tag')
    for tag in tags:
        if tag.get('k') == 'name:en':
            return tag.get('v')
    return "Junction"

def StreetName(way):
    tags = way.findall('tag')
    for tag in tags:
        if tag.get('k') == 'name:en':
            return tag.get('v')
    return "Street"


def ProcessWay(way):
    node_seq = way.findall('nd')
    highway_type = GetHighwayType(way)
    name = StreetName(way)
    AddNodeSeq(node_seq,highway_type,name)
    if not OnewayStreet(way):
        node_seq.reverse()
        AddNodeSeq(node_seq,highway_type,name)
        
 
 
def ComputePathLength(node_seq):
    total = 0.0
    for i in range(0,len(node_seq)-1):
        n1=node_seq[i]
        n2=node_seq[i+1]
        id1 = n1.get('ref')
        id2 = n2.get('ref')
        raw_node1 = RAW_NODE_TABLE[id1]
        raw_node2 = RAW_NODE_TABLE[id2]
        lat1 = float(raw_node1.get('lat'))
        lon1 = float(raw_node1.get('lon'))
        lat2 = float(raw_node2.get('lat'))
        lon2 = float(raw_node2.get('lon'))
        distance = MAP.ComputeDistance(lat1,lon1,lat2,lon2)
        total += distance
    return total


       
def AddNodeSeq(node_seq,highway_type,name):
    if ALL_LINKS:
        for i in range(0,len(node_seq)-1):
            AddLink(node_seq[i],node_seq[i+1],highway_type,name,None)
    else:
        path_length = ComputePathLength(node_seq)
        AddLink(node_seq[0],node_seq[-1],highway_type,name,path_length)

              
            
def AddLink(n1,n2,highway_type,name,distance):
    string_id1 = n1.get('ref')
    string_id2 = n2.get('ref')
    raw_node1 = RAW_NODE_TABLE[string_id1]
    raw_node2 = RAW_NODE_TABLE[string_id2]
    lat1 = float(raw_node1.get('lat'))
    lon1 = float(raw_node1.get('lon'))
    lat2 = float(raw_node2.get('lat'))
    lon2 = float(raw_node2.get('lon'))
    if distance == None:
        distance = MAP.ComputeDistance(lat1,lon1,lat2,lon2)
    distance = int(distance * 1000)  #Convert to meters so int is used instead of float
    if not string_id1 in JUNCTIONS_NAMES_TO_IDS:
        index_source = len(JUNCTIONS)
        JUNCTIONS_NAMES_TO_IDS[string_id1] = index_source
        source_junction = osm.junction(lat1,lon1,JunctionName(raw_node1),[])
        JUNCTIONS.append(source_junction)
    else:
        source_junction = JUNCTIONS[JUNCTIONS_NAMES_TO_IDS[string_id1]]
    if not string_id2 in JUNCTIONS_NAMES_TO_IDS:
        index_target = len(JUNCTIONS)
        JUNCTIONS_NAMES_TO_IDS[string_id2] = index_target
        JUNCTIONS.append(osm.junction(lat2,lon2,JunctionName(raw_node2),[]))
    else:
        index_target = JUNCTIONS_NAMES_TO_IDS[string_id2]
    source_junction.links.append(osm.link(index_target,distance,name,GetHighwayTypeIndex(highway_type),None))


def ImportMap(filename = DEFAULT_FILE):
    global RAW_NODE_TABLE
    global JUNCTIONS
    global JUNCTIONS_NAMES_TO_IDS
    JUNCTIONS = []
    JUNCTIONS_NAMES_TO_IDS = {}
    print "Parsing XML file ....(this will take awhile)"
    tree = ET.parse(filename)
    root = tree.getroot()
    print "Finding all nodes"
    raw_nodes = root.findall('node')
    print "Found " , len(raw_nodes) , " raw nodes"
    print "Creating hash table for raw nodes"
    for n in raw_nodes:
        RAW_NODE_TABLE[n.get('id')] = n
    print "Hash table created"
    print "Finding all ways"
    ways = root.findall('way')
    print "Found ", len(ways), " ways"
    print "Finding driveable ways"
    driveable_ways = [w for w in ways if GetHighwayType(w) in osm.DRIVEABLE_HIGHWAYS]
    print "Found " , len(driveable_ways), " driveable ways"
    i = 0
    for w in driveable_ways:
        i +=1   
        ProcessWay(w)
        if i % 10000 == 0:
          print i, " of ", len(driveable_ways)
    newname = filename + ".pickled"
    f = open(newname,"w")
    print 'Dumping map data structures to file ', newname
    pickle.dump(JUNCTIONS,f)
    f.close()
    
ImportMap()
    
    

